<template>
  <div class="list" ref="scrollWrapperRef" @scroll="scrollEvent">
    <div class="list-phantom" :style="{ height: listHeight + 'px' }" />
    <div class="scroll-wrapper" :style="{ transform: getTransform }">
      <div
        class="scroll-item"
        v-for="(item, index) in visibleData"
        :key="index"
      >
        {{ item.value }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import listData from "@/constants/data";

// 定义默认值
const itemSize = 50;
let endItem = ref(0);
let startItem = ref(0);
let screenHeight = ref(0);
const startOffset = ref(0);
const scrollWrapperRef = ref<HTMLElement | null>(null);
const listHeight = computed(() => {
  return listData.list.length * itemSize;
});
const visibleCount = computed(() => {
  return Math.ceil(screenHeight.value / itemSize);
});
const getTransform = computed(() => {
  return `translate3d(0, ${startOffset.value}px, 0)`;
});

let visibleData = computed(() => {
  return listData.list.slice(startItem.value, endItem.value);
});

onMounted(() => {
  startItem.value = 0;
  screenHeight.value = document.documentElement.clientHeight;
  endItem.value = startItem.value + visibleCount.value;
});

const scrollEvent = () => {
  //当前滚动位置
  let scrollTop = scrollWrapperRef.value?.scrollTop || 0;
  //此时的开始索引
  startItem.value = Math.floor(scrollTop / itemSize);
  //此时的结束索引
  endItem.value = startItem.value + visibleCount.value;
  //此时的偏移量
  startOffset.value = scrollTop - (scrollTop % itemSize);
};
</script>

<style lang="less" scoped>
.list {
  height: 100%;
  overflow: auto;
  position: relative;
  -webkit-overflow-scrolling: touch;

  .list-phantom {
    z-index: -1;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
  }

  .scroll-wrapper {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;

    .scroll-item {
      height: 50px;
      border-bottom: 1px solid #ccc;
      box-sizing: border-box;
      line-height: 50px;
    }
  }
}
</style>
